package main

import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/*
一对多
	外键: 外键必须存在，默认外键额名字是所有者类型的名字加上它的主键
	案列： 定义一个UserInfo表，再定义一个CardInfo表，其中UserInfoId为CardInfo表的外键
*/
//2、创建字段
type UserInfo struct {
	gorm.Model
	ID     uint
	Name   string `json:"name" gorm:"column:name"`
	Gender string `json:"gender" gorm:"column:gender"`
	Hobby  string `json:"hobby" gorm:"column:hobby"`
	// 添加外键关联  可以通过为标签 constraint 配置 OnUpdate、OnDelete 实现外键约束，在使用 GORM 进行迁移时它会被创建
	CardInfos []CardInfo `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}
type CardInfo struct {
	gorm.Model
	Number string
	//定义外键  这个就是与userInfo表关联的外键
	UserInfoId uint
}

func main() {
	//	1、连接mysql数据库
	dsn := "root:123@tcp(127.0.0.1:3306)/db2?charset=utf8&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)

	}
	//	3、创建表  自动迁移指的是把userinfo结构体和数据表进行对应
	db.AutoMigrate(&UserInfo{}, &CardInfo{})
	//	4、创建一对多   Association方法一对多查询
	// 4.1创建一对多关联表
	//user := UserInfo{
	//	Name: "张三",
	//	CardInfos: []CardInfo{
	//		{Number: "0001"},
	//		{Number: "0002"},
	//	},
	//}
	//db.Create(&user)
	//	4.2给张三用户增加一个Card信息  Association方法，需要把需要的用户查询好，然后根据用户中定义的关联外键去找到Card，在调用Append方法
	//     给CardInfo表中增加数据
	//  4.2关联表添加数据
	//user := UserInfo{Name: "张三"}
	//db.First(&user)
	//db.Model(&user).Association("CardInfos").Append([]CardInfo{
	//	{Number: "0003"},
	//	{Number: "0004"},
	//})
	//	4.3关联表查找数据 --Association方法 需要把需要的用户查询好，然后根据用户中定义的关联外键去找到Card
	//user := UserInfo{Name: "张三"}
	//db.First(&user)
	//if err := db.Model(&user).Association("CardInfos").Find(&user.CardInfos); err != nil {
	//	panic(err)
	//}
	////将数据序列化为json格式
	//if strUser, err := json.Marshal(&user); err != nil {
	//	panic(err)
	//} else {
	//	fmt.Println(string(strUser))
	//}
	//	5、一对多  Preload预加载方法进行一对多查询 (查询过程中将关联数据已经进行了预加载，与Assocation方法相比少了获取主键表的数据)
	user := []UserInfo{}
	db.Preload("CardInfos").Find(&user)
	strUser, _ := json.Marshal(&user)
	fmt.Println(string(strUser))
}
